using System;
using System.ComponentModel;

using DevExpress.Xpo;
using DevExpress.Xpo.Metadata;
using DevExpress.Data.Filtering;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.ExpressApp.Security.Strategy;

namespace WaTP.Module.BusinessObjects
{
    public class RequiredTicketBase : BaseObject
    {
        public RequiredTicketBase(Session session)
            : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here or place it only when the IsLoading property is false:
            // if (!IsLoading){
            //    It is now OK to place your initialization code here.
            // }
            // or as an alternative, move your initialization code into the AfterConstruction method.
        }
        private Department department;
        [RuleRequiredField(DefaultContexts.Save)]
        public Department Department {
            get { return department; }
            set { SetPropertyValue("Department", ref department, value); }
        }
        private DateTime expectedDate;
        public DateTime ExpectedDate
        {
            get { return expectedDate; }
            set { SetPropertyValue("ExpectedDate", ref expectedDate, value); }
        }
        private DateTime? completedDate;
        public DateTime? CompletedDate
        {
            get { return completedDate; }
            set { SetPropertyValue("CompletedDate", ref completedDate, value); }
        }
        //user
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            // Place here your initialization code.
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
    }
    [DefaultClassOptions]
    public class TransferRequiredTicket : RequiredTicketBase {
        public TransferRequiredTicket(Session session) : base(session) { }
        private string ticketCode;
        public string TicketCode {
            get {
                if (Department != null && Type != null)
                {
                    ticketCode = "T" + Type.OrderTypeID + Department.DepartmentID + "-" + FormatDateTime(StartDateTime);
                }
                return ticketCode;
            }
        }

        //
        private OrderCategory category;
        public OrderCategory Category
        {
            get { return category; }
            set { SetPropertyValue("Category", ref category, value); }
        }
        private OrderType type;
        [DataSourceProperty("Category.Types")]
        public OrderType Type
        {
            get { return type; }
            set { SetPropertyValue("Type", ref type, value); }
        }
        [Persistent("StartDateTime"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime startDateTime = DateTime.Now;
        [PersistentAlias("startDateTime")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime StartDateTime
        {
            get { return startDateTime; }
            //set { SetPropertyValue("StartDateTime", ref startDateTime, value); }
        }
        internal virtual void UpdateCreatedOn()
        {
            UpdateCreatedOn(DateTime.Now);
        }
        internal virtual void UpdateCreatedOn(DateTime date)
        {
            startDateTime = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "TicketCode")
            {
                UpdateCreatedOn();
            }
        }
        private string FormatDateTime(DateTime date)
        {
            string temp = null;
            string stringDate = date.ToString();
            for (int i = 0; i < stringDate.Length; i++)
            {
                if ((stringDate[i] != '/') && (stringDate[i] != '-') & (stringDate[i] != ':') && (stringDate[i] != ' '))
                {
                    temp += stringDate[i].ToString();
                }
            }
            return temp;
        }
        private bool canceled;
        public bool Canceled
        {
            get { return canceled; }
            set { SetPropertyValue("Canceled", ref canceled, value); }
        }
        //detail count
        [Persistent("DetailCount")]
        private int? fDetailCount = null;
        [PersistentAlias("fDetailCount")]
        public int? DetailCount
        {
            get
            {
                if (!IsLoading && !IsSaving && fDetailCount == null)
                    UpdateDetailsCount(false);
                return fDetailCount;
            }
        }
        public void UpdateDetailsCount(bool forceChangeEvents)
        {
            int? olderDetailsCount = fDetailCount;
            fDetailCount = Convert.ToInt32(Session.Evaluate<TransferRequiredTicket>(CriteriaOperator.Parse("TicketDetails.Count"),
                CriteriaOperator.Parse("Oid=?", Oid)));
            if (forceChangeEvents)
                OnChanged("OrdersCount", olderDetailsCount, fDetailCount);
        }

        //orders count
        [Persistent("OrdersCount")]
        private int? fOrdersCount = null;
        [PersistentAlias("fOrdersCount")]
        public int? OrdersCount
        {
            get
            {
                if (!IsLoading && !IsSaving && fOrdersCount == null)
                    UpdateOrdersCount(false);
                return fOrdersCount;
            }
        }
        public void UpdateOrdersCount(bool forceChangeEvents)
        {
            int? oldOrdersCount = fOrdersCount;
            fOrdersCount = Convert.ToInt32(Session.Evaluate<TransferRequiredTicket>(CriteriaOperator.Parse("OrderDetails.Count"),
                CriteriaOperator.Parse("Oid=?", Oid)));
            if (forceChangeEvents)
                OnChanged("OrdersCount", oldOrdersCount, fOrdersCount);
        }
        //completed orders count
        [Persistent("CompletedOrdersCount")]
        private int? fCompletedOrdersCount = null;
        [PersistentAlias("fCompletedOrdersCount")]
        public int? CompletedOrdersCount
        {
            get
            {
                if (!IsLoading && !IsSaving && fCompletedOrdersCount == null)
                    UpdateCompletedOrdersCount(false);
                return fCompletedOrdersCount;
            }
        }
        public void UpdateCompletedOrdersCount(bool forceChangeEvents)
        {
            int? oldCompletedOrdersCount = fCompletedOrdersCount;
            int temp = 0;
            foreach (TransferOrder detail in OrderDetails)
                if (detail.Status == TransferOrderStatus.Completed)
                    temp++;
            fCompletedOrdersCount = temp;
            if (forceChangeEvents)
                OnChanged("OrdersCount", oldCompletedOrdersCount, fCompletedOrdersCount);
        }
        private TicketStatus status;
        public TicketStatus Status {
            get {
                if (CompletedDate != null)
                {
                    if (CompletedOrdersCount > 0)
                        status = TicketStatus.Completed;
                    else
                    {
                        status = TicketStatus.Required;
                        CompletedDate = null;
                    }
                }
                else
                {
                    if (Canceled == false)
                    {
                        if (OrdersCount <= 0)
                        {
                            status = TicketStatus.Required;
                        }
                        else
                        {
                            if (OrdersCount > 0)
                            {
                                status = TicketStatus.InProgress;
                            }
                        }
                    }
                    else
                        status = TicketStatus.Canceled;
                }
                return status; }
        }
        [Association("TransferTicket-Details"), Aggregated]
        public XPCollection<TransferTicketDetail> TicketDetails
        {
            get { return GetCollection<TransferTicketDetail>("TicketDetails"); }
        }
        [Association("TransferTicket-Orders"), Aggregated]
        public XPCollection<TransferOrder> OrderDetails {
            get { return GetCollection<TransferOrder>("OrderDetails"); }
        }
        private void Reset()
        {
            fDetailCount = null;
            fOrdersCount = null;
            fCompletedOrdersCount = null;
        }
        protected override void OnLoaded()
        {
            Reset();
            base.OnLoaded();
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            status = TicketStatus.Required;
        }
    }

    public class TransferTicketDetail : BaseObject { 
        public TransferTicketDetail(Session session) : base(session){}
        private string requiredProduct;
        public string RequiredProduct
        {
            get { return requiredProduct; }
            set { SetPropertyValue("RequiredProduct", ref requiredProduct, value); }
        }
        private int quantity;
        public int Quantity
        {
            get { return quantity; }
            set { SetPropertyValue("Quantity", ref quantity, value); }
        }
        [Persistent("CreateOn"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime _CreateOn = DateTime.Now;
        [PersistentAlias("_CreateOn")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime CreateOn
        {
            get { return _CreateOn; }
        }
        internal virtual void UpdateCreatedOn()
        {
            UpdateCreatedOn(DateTime.Now);
        }
        internal virtual void UpdateCreatedOn(DateTime date)
        {
            _CreateOn = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "RequiredProduct")
            {
                UpdateCreatedOn();
            }
        }
        //User.
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
        private TransferRequiredTicket ticket;
        [Association("TransferTicket-Details")]
        public TransferRequiredTicket Ticket {
            get { return ticket; }
            set {
                TransferRequiredTicket oldTicket = ticket;
                SetPropertyValue("Ticket", ref ticket, value);
                if (!IsLoading && !IsSaving && oldTicket != ticket)
                {
                    oldTicket = oldTicket ?? ticket;
                    oldTicket.UpdateDetailsCount(true);
                }
            }
        }
    }
    public enum TicketStatus
    {
        [ImageName("State_Task_NotStarted")]
        Required,
        [ImageName("State_Task_InProgress")]
        InProgress,
        [ImageName("State_Task_Completed")]
        Completed,
        [ImageName("State_Validation_Invalid")]
        Canceled
    }
}
